package com.javabasic.algorithm.baidu_interview;





import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author mir.xiong
 * @version 1.0
 * @description
 * @see
 * @since Created by work on 2022/2/24 5:51 下午
 */

public class Test2 {

    public static void main(String[] args) {
        ConcurrentHashMap<Long, ConcurrentHashMap<Lock, List<Condition>>> timeToConditionMap = new ConcurrentHashMap<>(16);
        Clock clock = new Clock(timeToConditionMap);
        Thread timeThread = new Thread(clock, "时钟线程");
        timeThread.start();
        long currentTimeMillis = System.currentTimeMillis();

        System.out.println("当前时间：" + currentTimeMillis);
        Worker workerA = new Worker(currentTimeMillis + 1000 * 10, timeToConditionMap);
        Worker workerB = new Worker(currentTimeMillis + 1000 * 5, timeToConditionMap);

        Thread workerAThread = new Thread(workerA, "A工作线程");
        Thread workerBThread = new Thread(workerB, "B工作线程");

        workerAThread.start();
        workerBThread.start();
    }
}

class Clock implements Runnable {
    private ConcurrentHashMap<Long, ConcurrentHashMap<Lock, List<Condition>>> timeToConditionMap;

    public Clock(ConcurrentHashMap<Long, ConcurrentHashMap<Lock, List<Condition>>> timeToConditionMap) {
        this.timeToConditionMap = timeToConditionMap;
    }

    @Override
    public void run() {
        while (true) {
            if (this.timeToConditionMap == null || this.timeToConditionMap.isEmpty()) {
                try {
                    Thread.sleep(2);
                } catch (InterruptedException e) {
                    System.out.println(e.getCause() + e.getMessage());
                    Thread.currentThread().interrupt();
                } finally {
                    continue;
                }
            }
            long currentTimeMillis = System.currentTimeMillis();

            for (Map.Entry<Long, ConcurrentHashMap<Lock, List<Condition>>> entry : this.timeToConditionMap.entrySet()) {

                if (entry.getKey() < currentTimeMillis) {
                    ConcurrentHashMap<Lock, List<Condition>> value = entry.getValue();
                    for (Map.Entry<Lock, List<Condition>> lockListEntry : value.entrySet()) {
                        lockListEntry.getKey().lock();
                        try {
                            for (Condition condition : lockListEntry.getValue()) {
                                condition.signalAll();
                            }
                        } finally {
                            lockListEntry.getKey().unlock();
                        }
                    }
                }
            }
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                System.out.println(e.getCause() + e.getMessage());
                Thread.currentThread().interrupt();
            }
        }
    }
}


class Worker implements Runnable {

    private ReentrantLock lock;
    /**
     * 截止时间戳
     */
    private long waitTime;
    private Condition condition;
    private ConcurrentHashMap<Long, ConcurrentHashMap<Lock, List<Condition>>> timeToConditionMap;

    public Worker(long waitTime, ConcurrentHashMap<Long, ConcurrentHashMap<Lock, List<Condition>>> timeToConditionMap) {
        this.lock = new ReentrantLock();
        this.waitTime = waitTime;
        this.timeToConditionMap = timeToConditionMap;
        this.condition = lock.newCondition();
        ConcurrentHashMap<Lock, List<Condition>> lockToConditions = this.timeToConditionMap.getOrDefault(this.waitTime, new ConcurrentHashMap<>(16));
        List<Condition> conditions = lockToConditions.getOrDefault(lock, new ArrayList<>());
        conditions.add(this.condition);
        lockToConditions.put(lock, conditions);
        this.timeToConditionMap.put(this.waitTime, lockToConditions);
    }

    @Override
    public void run() {
        lock.lock();
        try {
            condition.await();
            System.out.println("================worker==============" + Thread.currentThread().getName() + "时间：");
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            lock.unlock();
        }
    }
}